///\file image.hh
///\brief contient les spécifications de la classe Image
///\author { V.Allombert, A.Blanchard, A.Carteron, V.Pelletier } 
#ifndef _IMAGE
#define _IMAGE

#include <IL/il.h>

///\struct pixel
///\brief définition d'un pixel (RGBA)
struct pixel{
  unsigned char r; ///< composante rouge
  unsigned char g; ///< composante verte
  unsigned char b; ///< composante bleue
  unsigned char a; ///< composante alpha
};

///\class Image
///\brief classe permettant de modéliser des images.
///la gestion de images est délégué à dev-IL.
///\warning Toutes les images chargées et enregistrées par cette classe 
///sont traitées en mode RGBA.
class Image{
private :
  static bool initialized; ///< dev-IL est-il initialisé ?
  
  ILuint i;       ///< Identifiant dev-IL de l'image
  pixel* data;    ///< pointeur vers le début des données
  unsigned int w; ///< largeur de l'image
  unsigned int h; ///< hauteur de l'image

  ///\brief Constructeur
  ///On interdit la création d'image sans dimension ou sans valeur
  Image();

  ///\brief Constructeur de copie
  ///La copie directe d'image est pour l'instant interdite
  Image( const Image& );

  ///\brief Opérateur d'affection
  ///L'affectation est pour l'instant interdite comme la copie
  Image& operator=( const Image& );

  ///\brief simplifie le bind d'image dev-IL pour l'utilisation interne
  inline void bind() const{ ilBindImage(i); }

public :

  ///\brief Constructeur
  ///construit une image en la chargeant depuis un fichier
  ///\param name : chemin vers le fichier d'entrée
  Image(const char* name);

  ///\brief Constructeur
  ///construit une image vide à partir de dimension
  ///\warning à ce moment le contenu de l'image EST TOTALEMENT INDEFINI.
  ///\param width largeur de l'image
  ///\param height hauteur de l'image
  Image(unsigned int width, unsigned int height);
  
  ///\brief Destructeur
  ///libère la mémoire allouée par dev-IL
  ~Image(){ if(i){ bind(); ilDeleteImages(1, &i); } };

  ///\brief permet le chargement d'une image post-construction
  ///\param name chemin vers le fichier d'entrée
  void load(const char* name);
  
  ///\brief permet la sauvegarde d'une image
  ///\param name chemin vers de le fichier de sortie
  ///\param ow s'il est vrai (défaut) on autorise l'écrasement, sinon non
  void save(const char* name, bool ow = true) const;

  ///\brief getter width
  ///\return largeur de l'image
  inline unsigned int width()  const{ return w; }
  
  ///\brief getter height
  ///\return hauteur de l'image
  inline unsigned int height() const{ return h; }
  
  ///\brief donne un accès vers le début d'une ligne
  ///\param i numéro de la ligne qu'on souhaite atteindre
  ///\return pointeur vers le début de la ligne i
  inline pixel* operator[](int i) const{ return &(data[i*w]); }
};

#endif
